package main

import (
	"fmt"
	"reflect"
	"time"
	"unsafe"
)

func testMemAllocWithNoPointer() {
	fmt.Println("testMemAllocWithNoPointer!")
	memAllocWithNotPointer()
	sh := (*reflect.SliceHeader)(unsafe.Pointer(&GlobalMemPoolNotPointer))
	fmt.Printf("A Data:%d,Len:%d,Cap:%d\n", sh.Data, sh.Len, sh.Cap)
	fmt.Printf("[size] current struct size is [%v]\n", unsafe.Sizeof(GlobalMemPoolNotPointer))

}

func testMemAllocWithPointer() {
	fmt.Println("testMemAllocWithPointer!")
	memAlloc()
	sh := (*reflect.SliceHeader)(unsafe.Pointer(&GlobalMemPool))
	fmt.Printf("A Data:%d,Len:%d,Cap:%d\n", sh.Data, sh.Len, sh.Cap)
	fmt.Printf("[size] current struct size is [%v]\n", unsafe.Sizeof(GlobalMemPool))
}

const (
	// MillionSize is 1M
	MillionSize = 1 << 20
)

type stMem struct {
	body [8 * MillionSize]byte
}

// GlobalMemPool is a pool of mem alloc
var GlobalMemPool []*stMem

// GlobalMemCnt is the cnt of mem alloc
var GlobalMemCnt uint64

var isInit bool

// ll
func lazyInit() {
	if isInit {
		return
	}
	isInit = true
	GlobalMemPool = make([]*stMem, 0)
	GlobalMemCnt = 0
}

// GlobalMemPoolNotPointer is global var
var GlobalMemPoolNotPointer []stMem

// GlobalMemPoolNotPointerCnt is cnt
var GlobalMemPoolNotPointerCnt uint64

func memAllocWithNotPointer() {
	st := stMem{}
	GlobalMemPoolNotPointer = append(GlobalMemPoolNotPointer, st)
	GlobalMemPoolNotPointerCnt++
	fmt.Printf("[alloc] mem cnt: [%v]\n", GlobalMemPoolNotPointerCnt)
}

func memAlloc() {
	st := stMem{}
	GlobalMemPool = append(GlobalMemPool, &st)
	GlobalMemCnt++
	fmt.Printf("[alloc] mem cnt: [%v]\n", GlobalMemCnt)
}

func main() {
	fmt.Println("alloc begin!")
	var st stMem
	fmt.Printf("[size] stMem struct size is [%v]\n", unsafe.Sizeof(st))
	for i := 0; i < 20; i++ {
		time.Sleep(time.Second * 1)
		testMemAllocWithNoPointer()
	}
}
